from django.utils.translation import gettext_lazy, gettext as _
from rest_framework.permissions import IsAuthenticated
from rest_framework.serializers import Serializer
from rest_framework.response import Response
from rest_framework.decorators import action
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
import pydantic

from core import errors
from utils.paginators import NoPaginatorInspector
from apps.api.paginations import NewPageNumberPagination100
from apps.api.viewsets import NormalGenericViewSet
from apps.app_tx_meeting.tx_clients.client import TxMeetingClient
from apps.app_tx_meeting.tx_clients import inputs as tx_inputs
from apps.app_tx_meeting import builders
from apps.app_tx_meeting.managers import MeetingUserWrapper


class TxCorpMeetingViewSet(NormalGenericViewSet):
    permission_classes = [IsAuthenticated]
    pagination_class = NewPageNumberPagination100
    lookup_field = 'id'

    @swagger_auto_schema(
        tags=['tx_meeting'],
        operation_summary=gettext_lazy('列举腾讯企业会议'),
        paginator_inspectors=[NoPaginatorInspector],
        manual_parameters=[
            openapi.Parameter(
                name='meeting_code',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=True,
                description=gettext_lazy('腾讯会议号，不能带连接符“-”或空格')
            ),
            openapi.Parameter(
                name='meeting_state',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_INTEGER,
                required=False,
                description=gettext_lazy('会议状态。1：结束会议，2：实时会议，3：即将开始的会议；默认为3')
            ),
        ],
        responses={
            200: ''''''
        }
    )
    def list(self, request, *args, **kwargs):
        """
        列举腾讯企业会议

            * 普通用户无权查看其他用户的会议信息，管理员可以查询所有会议信息

            http code 200:
            {
                "current_page": 1,  # 当前页码
                "current_size": 1,  # 当前页实际数量条数
                "total_count": 2,   # 数据总条数
                "total_page": 1,    # 数据总页数
                "meeting_info_list": [  # 会议对象列表
                    {
                        "meeting_id": "6090539079429244376",    # 会议 ID
                        "meeting_code": "35945211730",      # 会议号码
                        "subject": "测试张三预定的会议",
                        "userid": "zhangsan@xx.cn",     # 创建者ID
                        "userid_type": 1,               # 创建者 ID 类型. 1：userid; 3：rooms_id
                        "nick_name": "张三",         # 创建者昵称
                        "start_time": 1745218800,   # 会议开始时间，单位秒。
                        "end_time": 1745236800,     # 会议结束时间，单位秒。
                        "online_member_num": 0,     # 在线人数。
                        "meeting_state": 3,         # 会议状态。1：结束会议；2：实时会议；3：即将开始的会议
                        "meeting_type": 1           # 会议类型。0：一次性会议；1：周期性会议；6：网络研讨会
                    }
                ]
            }

            http code 403:
            {
                "code": "NotOwner",
                "message": "登录账号与腾讯会议的预定账号不符，请使用预定腾讯会议的账号登录查询和预约。"
            }
        """
        meeting_code = request.query_params.get('meeting_code', None)
        meeting_state = request.query_params.get('meeting_state', None)

        if not meeting_code:
            return self.exception_response(exc=errors.InvalidArgument(message=_('必须提交会议号')))

        if meeting_state:
            if meeting_state not in ['1', '2', '3']:
                return self.exception_response(exc=errors.InvalidArgument(message=_('会议状态可选值为 1、2、3')))
            else:
                meeting_state = int(meeting_state)
        else:
            meeting_state = 3

        try:
            params = tx_inputs.ListMeetingsInput(
                meeting_state=meeting_state,
                meeting_code=meeting_code
            )
        except pydantic.ValidationError as exc:
            msg = TxMeetingClient.get_msg_pydantic_error(exc)
            return self.exception_response(exc=errors.InvalidArgument(message=msg))

        client = builders.build_tx_meeting_client()
        r = client.list_corp_meetings(params=params)
        if not r.ok:
            return self.exception_response(exc=r.error)

        # 会议信息的查询权限
        if r.data.meeting_info_list:
            # 腾讯会议的创建者和会议预定用户必须一致，管理员除外
            tx_meeting_userid = r.data.meeting_info_list[0].userid
            if tx_meeting_userid != request.user.username:
                meeting_user = MeetingUserWrapper(user=request.user)
                if not meeting_user.is_admin():
                    return self.exception_response(
                        exc=errors.AccessDenied(
                            code='NotOwner',
                            message=_('登录账号与腾讯会议的预定账号不符，请使用预定腾讯会议的账号登录查询和预约。')))

        data = r.data.model_dump()
        return Response(data)

    @swagger_auto_schema(
        tags=['tx_meeting'],
        operation_summary=gettext_lazy('通过会议号查询腾讯企业会议信息'),
        paginator_inspectors=[NoPaginatorInspector],
        manual_parameters=[
            openapi.Parameter(
                name='meeting_code',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=True,
                description=gettext_lazy('腾讯会议号，不能带连接符“-”或空格')
            )
        ],
        responses={
            200: ''''''
        }
    )
    @action(methods=['GET'], detail=False, url_path='code', url_name='code')
    def get_meeting_by_code(self, request, *args, **kwargs):
        """
        通过会议号查询腾讯企业会议信息

            http code 200:
            {
                "meeting_number": 1,
                "meeting_info_list": [
                    {
                        "meeting_id": "6090539079429244376",    # 会议 ID
                        "meeting_code": "35945211730",      # 会议号码
                        "subject": "测试张三预定的会议",
                        "start_time": 1745218800,   # 会议开始时间，单位秒。
                        "end_time": 1745236800,     # 会议结束时间，单位秒。
                        "meeting_type": 1,           # 会议类型。0：一次性会议；1：周期性会议；2：微信专属会议
                                                            4：Rooms 投屏会议; 5：个人会议号会议;6：网络研讨会
                        "status": "MEETING_STATE_INIT"  # 当前会议状态
                    }
                ]
            }

            # status，当前会议状态：
            # MEETING_STATE_INVALID：非法或未知的会议状态，错误状态。
            # MEETING_STATE_INIT：会议待开始。会议预定到预定结束时间前，会议尚无人进会。
            # MEETING_STATE_CANCELLED：会议已取消。主持人主动取消会议，待开始的会议才能取消，且取消的会议无法再进入。
            # MEETING_STATE_STARTED：会议已开始。会议中有人则表示会议进行中。
            # MEETING_STATE_ENDED：会议已删除。会议已过预定结束时间且尚无人进会时，主持人删除会议，已删除的会议无法再进入。
            # MEETING_STATE_NULL：会议无状态。会议已过预定结束时间，会议尚无人进会。
            # MEETING_STATE_RECYCLED：会议已回收。会议已过预定开始时间30天，则会议号将被后台回收，无法再进入。
        """
        meeting_code = request.query_params.get('meeting_code', None)

        if not meeting_code:
            return self.exception_response(exc=errors.InvalidArgument(message=_('必须提交会议号')))

        try:
            params = tx_inputs.GetMeetingDetailByCodeInput(
                meeting_code=meeting_code, instanceid=5
            )
        except pydantic.ValidationError as exc:
            msg = TxMeetingClient.get_msg_pydantic_error(exc)
            return self.exception_response(exc=errors.InvalidArgument(message=msg))

        client = builders.build_tx_meeting_client()
        r = client.get_meeting_detail_by_code(params=params)
        if not r.ok:
            return self.exception_response(exc=r.error)

        data = {
            'meeting_number': r.data.meeting_number
        }
        if r.data.meeting_info_list:
            meeting_info_list = []
            for m in r.data.meeting_info_list:
                meeting_info_list.append({
                    'meeting_id': m.meeting_id,
                    'meeting_code': m.meeting_code,
                    'subject': m.subject,
                    'start_time': int(m.start_time),
                    'end_time': int(m.end_time),
                    'meeting_type': m.meeting_type,
                    'status': m.status,
                })

            data['meeting_info_list'] = meeting_info_list
        else:
            data['meeting_info_list'] = []

        return Response(data=data)

    def get_serializer_class(self):
        return Serializer
